﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Security.Cryptography;

namespace MabiPatch
{
	/// <summary>
	/// Description of Common.
	/// </summary>
	public class Common
	{
		public static void WriteVersion(int Version)
		{
            byte[] b = BitConverter.GetBytes(Version);
            File.WriteAllBytes("version.dat", b);
		}
		public static int ReadVersion()
		{
            try
            {
                byte[] d = new byte[sizeof(int)];
                using (FileStream f = File.OpenRead("version.dat"))
                {
                    f.Read(d, 0, sizeof(int));
                }
                return BitConverter.ToInt32(d, 0);
            }
            catch (Exception)
            {
                return 0;
            }
		}
		public static List<string> FTPGetListing(string SubFolder)
		{
            string requestURL = "ftp://mabipatch.nexon.net";
            if (SubFolder != null)
                requestURL += "/" + SubFolder;
			FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(requestURL);
			ftp.KeepAlive = false;
			ftp.Method = WebRequestMethods.Ftp.ListDirectory;
			ftp.UsePassive = true;
			ftp.Credentials = new NetworkCredential("anonymous", "anonymous");
			
			List<string> dir = new List<string>();
			using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
			{
				using (StreamReader r = new StreamReader(response.GetResponseStream()))
		        {
					while (!r.EndOfStream)
						dir.Add(Path.GetFileName(r.ReadLine()));
		        }
			}
			return dir;
		}
		public static List<int> GetAvailableVersions()
		{
			List<int> versions = new List<int>();
			List<string> dir = FTPGetListing(null);
			foreach (string d in dir)
			{
				try
				{
					versions.Add(int.Parse(d));
				}
				catch {}
			}
			versions.Sort();
			return versions;
		}
		public static List<string> TraceVersions(int startVersion, int endVersion)
		{
            List<int> versions = GetAvailableVersions();
            if (endVersion == -1)
                endVersion = versions[versions.Count-1];
            List<string> vStack = TraceRecurse(startVersion, endVersion, versions);
            if (vStack.Count == 0)
                vStack.Add(endVersion + "_full");
            return vStack;
		}
        private static List<string> TraceRecurse(int start, int end, List<int> versions)
        {
            List<string> vStack = new List<string>();
            if (start != end && versions.Contains(start))
            {
                Patcher.info.SupUpdaters[0].Invoke(start / (double)end, "Tracing " + start + " to " + end + "..."); 
                if (FTPGetListing(end.ToString()).Contains(start + "_to_" + end + ".txt"))
                {
                    vStack.Add(start + "_to_" + end);
                }
                else 
                {
                    for (int i = versions.IndexOf(start) + 1; i < versions.Count; i++)
                    {
                        Patcher.info.SupUpdaters[0].Invoke(versions[i] / (double)end, "Tracing " + start + " to " + versions[i] + "..."); 
                        if (!FTPGetListing(versions[i].ToString()).Contains(start + "_to_" + versions[i] + ".txt"))
                        {
                            vStack.Add(start + "_to_" + versions[i - 1]);
                            vStack.AddRange(TraceRecurse(versions[i - 1], end, versions));
                            break;
                        }
                    }
                }
            }
            return vStack;
        }

        public static string GetLastVersion(string BasePatchName)
        {
            int end = BasePatchName.LastIndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
            if (end == -1)
                throw new ArgumentException("'" + BasePatchName + "' does not contain any numbers.");
            int start = end;
            while (start >= 0 && IsNumeric(BasePatchName[start].ToString()))
                start--;
            start++;
            return BasePatchName.Substring(start, end - start + 1);

        }
        public static bool IsNumeric(string value)
        {
            double x;
            return double.TryParse(value, out x);
        }
        public static string MD5(string fileName)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                using (FileStream file = new FileStream(fileName, FileMode.Open))
                {
                    byte[] retVal = md5.ComputeHash(file);
                    return BitConverter.ToString(retVal).Replace("-", "").ToLower(); // hex string
                }
            }
        }
        public static List<string> FindFiles(string Path)
        {
        	List<string> fList = Directory.GetFiles(Path).ToList();
        	string[] dirs = Directory.GetDirectories(Path);
        	foreach (string d in dirs)
        		fList.AddRange(FindFiles(d));
        	return fList;
        	
        }
        public static bool TreeEmpty(string path)
        {
            try
            {
                if (Directory.GetFiles(path).Length != 0)
                    return false;
                string[] dirs = Directory.GetDirectories(path);
                foreach (string d in dirs)
                {
                    if (!TreeEmpty(Path.Combine(path, d)))
                        return false;
                }
            }
            catch { }
        	return true;
        }
	}
}
